package com.mvc.security.service;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mvc.framework.model.Auditable;
import com.mvc.framework.service.BaseService;
import com.mvc.security.model.User;
import com.mvc.security.model.UserRole;
import com.mvc.security.util.SecurityUtils;

@Service
public class UserManager<T extends User> extends BaseService<User, Integer> {
	@Autowired
	protected UserDepartmentManager userDepartmentManager;
	@Autowired
	protected DepartmentManager departmentManager;

	public boolean authentication(User user) {
		boolean result = false;
		String loginName = user.getLoginName();
		String password = user.getPassword();
		User realUser = null;
		if (loginName != null && loginName.length() > 0) {
			if (password != null && password.length() > 0) {
				realUser = getUserByLoginName(loginName);
			}
		} else {
			if (User.USER_TYPE_MEMBER == user.getType()) {
				if (user.getEmail() != null && user.getEmail().length() > 0) {
					if (password != null && password.length() > 0) {
						realUser = getUserByEmail(user.getEmail());
					}
				}
			}
		}
		if (null != realUser && null != realUser.getPassword()
		        && realUser.getPassword().equals(SecurityUtils.generatePassword(password))) {
			result = true;
		}
		return result;
	}

	public void save(User entity) {
		if (null == entity.getObjectId()) {
			entity.setPassword(SecurityUtils.generatePassword(entity.getPassword()));
		}
		super.save(entity);
	}

	public User getUserWithDepartment(Integer id) {
		User user = super.get(id);
		user.setDepartment(departmentManager.getDepartmentByDepartmentId(user.getDepartmentId()));
		return user;
	}

	public User getUserByUserId(Integer userId) {
		User user = getByObjectId(userId);
		if (user != null) {
			user.setDepartment(departmentManager.getDepartmentByDepartmentId(user.getDepartmentId()));
			return user;
		}
		return null;
	}

	public User getUserByLoginName(String loginName) {
		User example = new User();
		example.setLoginName(loginName);
		example.setRecStatus(Auditable.REC_STATUS_VALID);
		List<User> users = getHibernateTemplate().findByExample(example);
		if (users.size() > 0) {
			User user = users.get(0);
			user.setDepartment(departmentManager.getDepartmentByDepartmentId(user.getDepartmentId()));
			return user;
		}
		return null;
	}

	public User getUserByLoginNameAndType(String loginName, Integer type) {
		User example = new User();
		example.setLoginName(loginName);
		example.setType(type);
		example.setRecStatus(Auditable.REC_STATUS_VALID);
		List<User> users = getHibernateTemplate().findByExample(example);
		if (users.size() > 0) {
			User user = users.get(0);
			user.setDepartment(departmentManager.getDepartmentByDepartmentId(user.getDepartmentId()));
			return user;
		}
		return null;
	}

	public User getUserByEmail(String email) {
		User example = new User();
		example.setEmail(email);
		List<User> users = getHibernateTemplate().findByExample(example);
		if (users.size() > 0) {
			User user = users.get(0);
			user.setDepartment(departmentManager.getDepartmentByDepartmentId(user.getDepartmentId()));
			return user;
		}
		return null;
	}

	public List<User> getUsersByKeyWords(String keyWords) {
		String sql = "select A from " + User.class.getName() + " A where loginName like '%" + keyWords + "%'";
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery(sql);
		List<User> list = query.list();
		session.close();
		return list;
	}

	public User getUserByMobilePhone(String mobilePhone) {
		User example = new User();
		example.setMobilePhone(mobilePhone);
		List<User> users = getHibernateTemplate().findByExample(example);
		if (users.size() > 0) {
			User user = users.get(0);
			user.setDepartment(departmentManager.getDepartmentByDepartmentId(user.getDepartmentId()));
			return user;
		}
		return null;
	}

	public void updatePassword(User user) {
		StringBuilder hql = new StringBuilder();
		hql.append("UPDATE ").append(User.class.getName()).append(" SET password = '").append(user.getPassword())
		        .append("' WHERE ").append("id = ").append(user.getId());
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery(hql.toString());
		query.executeUpdate();
		session.close();
	}

	public List<User> getAll() {
		User user = new User();
		user.setRecStatus(Auditable.REC_STATUS_VALID);
		return getHibernateTemplate().findByExample(user);
	}

	public List<User> getUsersByRoleId(Integer roleId) {
		String sql = "SELECT  A from  " + User.class.getName() + " A," + UserRole.class.getName() + " D "
		        + "WHERE A.recStatus = " + Auditable.REC_STATUS_VALID + " AND D.recStatus = "
		        + Auditable.REC_STATUS_VALID + " AND A.objectId = D.userId AND D.roleId = " + roleId;
		return searchBySql(sql);
	}

	public Long getUserCount() {
		String sql = "select count(*) from " + User.class.getName() + " where recStatus = "
		        + Auditable.REC_STATUS_VALID;
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery(sql);
		Long result = ((Long) query.iterate().next());
		session.close();
		return result;
	}

	public List<User> getUserByUserType(int userType) {
		String sql = "select A from " + User.class.getName() + " A where A.recStatus = ? and A.type = ?";
		return searchBySql(sql, new Object[] { Auditable.REC_STATUS_VALID, userType });
	}

	public User checkIfExistsUser(User user) {
		String sql = "select A from " + User.class.getName() + " A where A.recStatus = ? and A.loginName = ?";
		Object[] parameters = new Object[] { Auditable.REC_STATUS_VALID, user.getLoginName() };
		Integer objectId = user.getObjectId();
		if (objectId != null) {
			sql += " and A.objectId != ?";
			parameters = new Object[] { Auditable.REC_STATUS_VALID, user.getLoginName(), objectId };
		}
		List<User> userList = searchBySql(sql, parameters);
		if (userList.size() > 0) {
			return userList.get(0);
		}
		return null;
	}

}
